--------------------------------------------------------------------------------
-- Entity: ControleReception
--------------------------------------------------------------------------------
-- Copyright ... 2010
-- Filename          : ControleReception.vhd
-- Creation date     : 2010-04-15
-- Author(s)         : salim
-- Version           : 1.00
-- Description       : Handles data reception and errors
--------------------------------------------------------------------------------
-- File History:
-- Date         Version  Author   Comment
-- 2010-04-15   1.00     salim     Creation of File
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity ControleReception is
	port  (
		clk : in std_logic;        -- input clock, 9,6 kHz.
		enable : in std_logic;		-- input clock, 155 kHz.
		reset : in std_logic;
		rxd : in std_logic;
		rd : in std_logic;
		data : out std_logic_vector(7 downto 0);
		FErr, OErr, DRdy : out std_logic
	);
end ControleReception;

architecture arch of ControleReception is

	type state is (init, start, stop);
	
	--signal bufEtmp : std_logic;
	--signal regEtmp : std_logic;
	signal etat : state := init;
	signal parity : std_logic := '0';
	signal parityC : std_logic := '1'; -- pour éviter de comparer 0 à 0 si
												  -- on rentre pas dans un if
	signal tmpdata : std_logic_vector(7 downto 0);
	
begin
--------------------------------------------------------------------------------
-- Algo:
-- 1 - wait the start bit is recived
-- 2 - recieve the 8 data bits from MSB to LSB
-- 3 - recieve the parity bit
-- 4 - recieve the stop bit
-- 5 - if stop bit equal 0, or parity bit is incorrect => error FErr = 1
--     else put Drdy = 1 and wait for rd = 1
--     (a) if at the next rising edge of enable rd = 1 the put Drdy = 0 and transmit
--         the data to the processor
--     (b) else put OErr = 1
--  
-- Be Carefull, steps 1,2,3,4 are punctuated by 
--------------------------------------------------------------------------------

	process (enable, reset) -- sensibilité sur l'horloge la plus rapide
								-- beaucoup d'attente active
		variable cpt : integer range -1 to 7 := 0;
		variable attenteRd : boolean := false;
	begin
	    if (reset = '0') then
			etat <= init;
			-- on réinitialise  les flags
			FErr <= '0';
			OErr <= '0';
			DRdy <= '0';
			
			cpt := 7;
		-- faut peut etre réagir sur front descendant de clk
		-- pour que le enable = 1 soit detecté sans un top d'horloge
		-- en retard 
		elsif (enable = '1' and enable'event) then
	        case etat is
		        when init =>
						cpt := 7;
						
						FErr <= '0';
						OErr <= '0';
						DRdy <= '0';
						
					-- attente du bit de start
	            	if(rxd = '0') then
							etat <= start;
						end if;

				when start =>
				-- bit de start reçu, on peut commencer à lire les données
					if(clk = '1') then
						if(cpt = -1) then
							-- la réception du dernier bit est effectuée
							-- on attend la réception du bit de parité
							parity <= rxd;
							
							-- on calcul le bit de parité à partir des données recues
							parityC <= tmpdata(0) xor tmpdata(1) xor tmpdata(2) xor tmpdata(3) xor tmpdata(4) xor tmpdata(5) xor tmpdata(6) xor tmpdata(7);
							
							-- L'éventuelle erreur de partié n'est pas gérée ici
							-- on passe à l'état stop pour gérer les erreurs
							etat <= stop;
						else
							-- lecture de la donnée se trouvant à la case cpt
							-- initialement cpt vaut 7
							tmpdata(cpt) <= rxd;
							
							-- on decremente cpt pour lire la donnée de poid inférieur
							cpt := (cpt - 1);
						end if;				
					end if;
					
				when stop =>
				-- reception du bit stop et gestion des erreurs
					if(clk = '1') then
						if(rxd = '1' or (not(parity) = parityC)) then
							FErr <= '1';
						else
						-- on positionne Drdy à 1 et on atten rd=1
							Drdy <= '1';
							attenteRd := true;
						end if;
					else
					
						-- on attend rd = 1 
						if(attenteRd = true) then 
							if (rd = '1') then
								Drdy <= '1';
								data <= tmpdata;
							else
								-- erreur de transimission
								OErr <= '1';
							end if;
						end if;
						
						-- on repasse à l'état init
						etat <= init;
					
					end if;
			end case;
		end if;
	end process;
end arch;

